#include <algorithm>
#include <stdexcept>

#include "vect.h"

vect::vect() : size_of(0), quantity(1)
{

}
vect::vect(long long digit) : size_of(1), quantity(1)
{
	box.num = digit;
}
vect::vect(const vect& vector) : size_of(vector.size_of), quantity(vector.quantity)
{
	if (quantity == 1)
	{
		box.num = vector.box.num;
	}
	else
	{
		box.a_nums = new long long[quantity];
		for (unsigned int i = 0; i < size_of; i++)
		{
			box.a_nums[i] = vector.box.a_nums[i];
		}
	}
}
vect::~vect()
{
	if (quantity > 1)
	{
		delete[] box.a_nums;
	}
}
vect& vect::operator = (const vect& vector)
{
	if (this == &vector)
	{
		return *this;
	}
	if (quantity > 1)
	{
		delete[] box.a_nums;
	}
	size_of = vector.size_of;
	quantity = vector.quantity;
	if (quantity > 1)
	{
		box.a_nums = new long long[quantity];
	}

	for (unsigned int i = 0; i < vector.size(); i++)
	{
		(*this)[i] = vector[i];
	}
	return *this;
}
unsigned int vect::size() const
{
	return size_of;
}
void vect::push(long long digit)
{
	grow();
	size_of++;
	(*this)[size_of - 1] = digit;
}

void vect::pop()
{
	if (size_of == 0)
	{
		throw std::runtime_error("No more elements!\n");
	}
	size_of--;
	shrink();
}
void vect::swap(vect& vector)
{
	std::swap(box, vector.box);
	std::swap(size_of, vector.size_of);
	std::swap(quantity, vector.quantity);
}
void vect::clear()
{
	if (quantity > 1)
	{
		delete[] box.a_nums;
		quantity = 1;
	}
	size_of = 0;
}
void vect::resize(unsigned int size, long long digit)
{
	while (quantity < size)
	{
		grow(true);
	}
	unsigned int temp = size_of;
	size_of = size;
	for (unsigned int i = temp; i < size_of; i++)
	{
		(*this)[i] = digit;
	}
	shrink();
}
void vect::insert(int i, int count, long long digit)
{
	unsigned int temp = size_of;
	resize(size_of + count, 0);
	for (int j = temp - 1; j >= i; j--)
	{
		(*this)[j + count] = (*this)[j];
	}
	for (int j = i; j < count; j++)
	{
		(*this)[j] = digit;
	}
}
unsigned int vect::begin()
{
	return 0;
}
long long& vect::operator[](unsigned int i)
{
	if (i >= size_of)
	{
		throw std::runtime_error("Index out of bounds!");
	}
	if (quantity == 1)
	{
		return box.num;
	}
	return box.a_nums[i];
}
long long vect::operator[](unsigned int i) const
{
	if (i >= size_of)
	{
		throw std::runtime_error("Index out of bounds!");
	}
	if (quantity == 1)
	{
		return box.num;
	}
	return box.a_nums[i];
}
void vect::grow(bool force)
{
	if (!force && size_of < quantity)
	{
		return;
	}
	long long* temp = new long long[2 * quantity];
	if (quantity == 1)
	{
		temp[0] = box.num;
	}
	else
	{
		for (unsigned int i = 0; i < size_of; i++)
		{
			temp[i] = box.a_nums[i];
		}
		delete[] box.a_nums;
	}
	box.a_nums = temp;
	quantity *= 2;
}
void vect::shrink()
{
	if (quantity == 1 || size_of * 4 >= quantity)
	{
		return;
	}
	if (quantity / 2 == 1)
	{
		long long temp = box.a_nums[0];
		delete[] box.a_nums;
		box.num = temp;
	}
	else
	{
		long long* temp = new long long[quantity / 2];
		for (unsigned int i = 0; i < size_of; i++)
		{
			temp[i] = box.a_nums[i];
		}
		delete[] box.a_nums;
		box.a_nums = temp;
	}
	quantity /= 2;
}